package org.hcyspartnoc.luoxin.utils.netty_chat;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.timeout.IdleStateHandler;
import org.hcyspartnoc.luoxin.common.core.configuration.NettyServerConfiguration;
import org.hcyspartnoc.luoxin.utils.SslUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

@Component
public class NettyWebSocketServer {
    private static final Logger logger = LoggerFactory.getLogger(NettyWebSocketServer.class);
    EventLoopGroup bossGroup = new NioEventLoopGroup(1);
    EventLoopGroup workGroup = new NioEventLoopGroup();

    @Resource
    private HeartBeatHandler VChatHeartBeatHandler;
    @Resource
    private WebSocketHandler VChatWebSocketHandler;
    @Resource
    private NettyServerConfiguration nettyServerConfiguration;

    @Async
    public void run() {
        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workGroup)
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .channel(NioServerSocketChannel.class) // 设置通道为nio服务套接字通道
                    .handler(new LoggingHandler(LogLevel.DEBUG)) // 配置日志处理，日志级别
                    .childHandler(new ChannelInitializer() {
                        @Override
                        protected void initChannel(Channel channel) throws Exception {
                            ChannelPipeline pipeline = channel.pipeline();


                            // 替换为你的证书和私钥文件路径
                            SslContext sslCtx = SslUtil.createSSLContext();
                            pipeline.addLast(sslCtx.newHandler(channel.alloc()));

                            pipeline.addLast(new HttpServerCodec());// 配置http解码器
                            pipeline.addLast(new HttpObjectAggregator(5 * 1024 * 1024));// 配置HTTP 对象聚合器

                            pipeline.addLast(new IdleStateHandler(nettyServerConfiguration.getHeartbeatInterval(), 0, 0, TimeUnit.SECONDS));//配置读写空闲
                            pipeline.addLast(VChatHeartBeatHandler);// 配置心跳处理器
                            // WebSocket协议升级处理器
                            pipeline.addLast(new WebSocketServerProtocolHandler(nettyServerConfiguration.getUrlPrefix(), null, true, 5 * 1024 * 1024, true, true, 10000L));//配置Web 套接字服务器协议处理程序
                            // 可选的，添加WebSocket数据压缩处理器
                            pipeline.addLast(new WebSocketServerCompressionHandler());
                            pipeline.addLast(VChatWebSocketHandler);//配置Web 套接字处理程序
                        }
                    });
            ChannelFuture channelFuture = serverBootstrap.bind(nettyServerConfiguration.getPort()).sync();
            logger.info("全局通信服务启动成功，端口:" + nettyServerConfiguration.getPort());
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            logger.error("全局通信服务启动失败", e);
        } finally {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
            logger.info("全局通信服务已退出");
        }
    }

    @PreDestroy
    public void beforeDestroy() {
        bossGroup.shutdownGracefully();
        workGroup.shutdownGracefully();
    }
}
